<?php

declare (strict_types=1);

namespace app\common\middleware;

use think\facade\Log;
use think\facade\Request;
use think\facade\Session;
use think\facade\Db;
use think\Response;

class OperationLogMiddleware
{
    /**
     * 处理请求
     *
     * @param \think\Request $request
     * @param \Closure $next
     * @return Response
     */
    public function handle($request, \Closure $next)
    {
        // 先执行请求
        $response = $next($request);

        // 请求完成后记录日志
        $this->recordLog();

        return $response;
    }

    /**
     * 记录操作日志
     */
    protected function recordLog()
    {
        try {
            // 获取当前请求信息
            $request = Request::instance();
            $endTime = microtime(true) * 1000;
            $startTime = $request->request_start_time * 1000;
            $runTime = bcsub((string) $endTime, (string) $startTime, 1);

            // 组装日志数据
            $logData = [
                'user_id' => Session::get('user.id') ?? 0, // 当前登录用户ID
                'username' => Session::get('user.username') ?? '未知用户', // 当前登录用户名
                'method' => $request->method(), // 请求方法
                'url' => $request->url(), // 请求URL
                'ip' => $request->ip(), // 客户端IP
                'param' => json_encode($request->param()), // 请求参数
                'user_agent' => $request->header('user-agent'), // 客户端信息
                'create_time' => date('Y-m-d H:i:s'), // 操作时间
                'run_time' => $runTime
            ];

            // 可以根据需要过滤不需要记录的请求
            if ($this->shouldRecord($logData)) {
                // 写入数据库
//                Db::name('operation_log')->insert($logData);

                // 同时记录到日志文件
                Log::info('操作日志: ' . json_encode($logData, JSON_UNESCAPED_UNICODE));
            }
        } catch (\Exception $e) {
            Log::error('记录操作日志失败: ' . $e->getMessage());
        }
    }

    /**
     * 判断是否需要记录日志
     *
     * @param array $logData
     * @return bool
     */
    protected function shouldRecord(array $logData): bool
    {
        // 过滤掉不需要记录的URL，例如静态资源、API文档等
        $excludeUrls = [
            '/favicon.ico',
            '/swagger',
            '/doc'
        ];

        foreach ($excludeUrls as $url) {
            if (strpos($logData['url'], $url) === 0) {
                return false;
            }
        }

        // 可以根据需要添加更多过滤条件
        return true;
    }
}
